<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>贪吃蛇</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            background-color:#20588b;
        }

        ul {
            list-style: none;
        }

        .container {
            width: 1000px;
            height:600px;
            margin: 10px auto;
            background-color: antiquewhite;
            position: relative;
        }

        .food {
            width: 20px;
            height: 20px;
            background-color: lightcoral;
            position: absolute;
        }

        /* .snake_body {
            position: relative;
        } */

        .snake_body .cube {
            position: absolute;
            width: 20px;
            height: 20px;
            background-color: #bff;
        }

        .cube.head {
            background-color:#20588b;
        }
    </style>
</head>

<body>
<div class="container">
    <ul class="snake_body">
    </ul>

</div>


<script>
    const container = document.querySelector('.container')

    const ul_body = document.querySelector('.snake_body')

    /*需求：
   1.小蛇朝着某个方向不断运动 （头部运动 身体也动 每节身体运动的位置是下一节的位置）
   2.上下左右能控制小蛇的运动方向
   3.随机生成食物
   4.碰到食物会增大
   5.碰到四周或自己 游戏结束
   6.采用vue 操作数据的思想 */

    let snake_arr = [
        { id: 0, left: 100, top: 100, move_direction: 'r' },
        { id: 1, left: 80, top: 100 },
        { id: 2, left: 60, top: 100 }]
    render_snake()
    function render_snake(flag = false) {
        if (flag) {
            ul_body.innerHTML = ''
        }
        for (let i = snake_arr.length - 1; i >= 0; i--) {
            let li = document.createElement('li')
            if (snake_arr[i].id == 0) {
                li.classList.add('cube', 'head')
            } else if (snake_arr[i].id == snake_arr.length - 1) {
                li.innerText = i
                li.classList.add('cube')
            }
            else {
                li.innerText = ''
                li.classList.add('cube')
            }
            li.style.left = snake_arr[i].left + 'px'
            li.style.top = snake_arr[i].top + 'px'

            ul_body.append(li)
        }
    }

    // 2.增加1节身体
    function add_body(n = 1) {
        for (let i = 0; i < n; i++) {
            let length = snake_arr.length
            // 直接加在最后一节身体的上面  虽然当时重合在了一起 但是下次移动时，倒数第二个位置会变到倒数第三个cube的位置，倒数第一个位置相当于没变动，就露出来了
            snake_arr.push({ id: length, left: snake_arr[length - 1].left, top: snake_arr[length - 1].top })
        }
        render_snake(true)
        // console.log(snake_arr)
    }

    // 3. 根据头部的方向移动
    function snake_move() {
        let d = snake_arr[0].move_direction

        /* lis:    [尾 5 4 3 2 1 0 头]
       snake_arr:  [头 0 1 2 3 4 5 尾]*/

        // 如果是操控dom元素的位置的话会比较难 所以直接改变存放小蛇数据的数组
        // 让每一节小蛇的身体都获取下一节的位置
        for (let i = snake_arr.length - 1; i >= 1; i--) {
            snake_arr[i].left = snake_arr[i - 1].left
            snake_arr[i].top = snake_arr[i - 1].top
        }

        // 头部单独处理 根据移动方向进行位置变化  这里取到20是因为小蛇每一节身体都是20*20px
        switch (d) {
            case 'l':
                snake_arr[0].left -= 20
                break
            case 'r':
                snake_arr[0].left += 20
                break
            case 'u':
                snake_arr[0].top -= 20
                break
            case 'd':
                snake_arr[0].top += 20
                break
        }
        render_snake(true)
    }

    let auto_move = setInterval(snake_move, 100)
    let lock = false
    function test_key(key) {
        if (!lock) {
            lock = true
            // console.log('我执行了');
            let d = snake_arr[0].move_direction
            let key_type = 'vertical'
            if (key == 'ArrowLeft' || key == 'ArrowRight') {
                key_type = 'level'
            } else {
                key_type = 'vertical'
            }
            if (key_type == 'level' && (d == 'r' || d == 'l')) {

            } else if (key_type == 'vertical' && (d == 'u' || d == 'd')) {
            } else {
                key_change_direction(key)
            }
            setTimeout(() => {
                lock = false
            }, 50)
        }
    }

    function key_change_direction(key) {

        switch (key) {
            case 'ArrowLeft':
                snake_arr[0].move_direction = 'l'
                break
            case 'ArrowRight':
                snake_arr[0].move_direction = 'r'
                break
            case 'ArrowUp':
                snake_arr[0].move_direction = 'u'
                break
            case 'ArrowDown':
                snake_arr[0].move_direction = 'd'
                break
            default:
                console.log(key);
        }


    }

    let timer = null
    function debounce(key) {
        if (timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(() => {
            test_key(key)
        }, 50)
    }
    window.addEventListener('keyup', (e) => {
        test_key(e.key)

    })
    function random_food() {
        // 0 - width/height 还得是20的倍数 这样20px * 20px的小蛇才能和食物完全重合
        let random_left = Math.floor(Math.random() * container.clientWidth / 20)
        let random_top = Math.floor(Math.random() * container.clientHeight / 20)

        let food = document.createElement('div')
        food.classList.add('food')
        food.style.left = random_left * 20 + 'px'
        food.style.top = random_top * 20 + 'px'

        container.append(food)
    }

    random_food()
    function get_position(domEle) {
        return [domEle.offsetLeft, domEle.offsetTop]
    }
    function eat_food() {
        let test_head_position
        let food = document.querySelector('.food')
        let [fl, ft] = get_position(food)
        test_head_position = setInterval(() => {
            let head = document.querySelector('.snake_body .head')
            let [hl, ht] = get_position(head)
            if (hl == fl && ht == ft) {
                clearInterval(test_head_position)
                food.parentElement.removeChild(food)
                random_food()
                eat_food()
                add_body(1)
            }
        }, 100)
    }

    eat_food()

    // 7.增加失败条件
    let container_w = container.offsetWidth
    let container_h = container.offsetHeight

    let test_failue = setInterval(() => {

        // 跑出圈外判负
        if (snake_arr[0].left >= container_w || snake_arr[0].left < 0 || snake_arr[0].top >= container_h || snake_arr[0].top < 0) {
            clearInterval(test_failue)
            clearInterval(auto_move)
        }
        else if (test_body()) {
            clearInterval(test_failue)
            clearInterval(auto_move)
        }
    }, 100)

    // 检测是否撞到了自己
    function test_body() {
        console.log(snake_arr[0].move_direction);
        for (let i = snake_arr.length - 1; i > 0; i--) {
            if (snake_arr[0].left == snake_arr[i].left && snake_arr[0].top == snake_arr[i].top) {
                return true
            }
        }
        return false
    }
</script>
</body>

</html>